/**
 * 需要全局变量：$
 * 需要knockout和knockout-validation
 * 需要CryptoJS和enc-base64
 * 需要artDialog
 * 需要perfect-scrollbar.jquery.js
 */
(function (factory) {
    if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
        factory(require("knockout"), exports,require("config"));
    } else if (typeof define === "function" && define["amd"]) {
        define(["knockout", "exports","config"], factory);
    } else {
        window.hr = window.hr || {};
        factory(ko, hr.common = hr.common || {});
    }
}(function (ko, exports) {
    if (typeof (ko) === 'undefined') {
        throw new Error('Knockout is required, please ensure it is loaded before loading this ko.common plug-in');
    }

    exports.sessionStorageUtil = {
        setItem: function (key, value) {
            sessionStorage.setItem(key, CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(JSON.stringify(value))));
        },
        getItem: function (key) {
            if (sessionStorage.getItem(key)) {
                return $.parseJSON((CryptoJS.enc.Base64.parse(sessionStorage.getItem(key))).toString(CryptoJS.enc.Utf8));
            }
        },
        removeItem: function (key) {
            sessionStorage.removeItem(key);
        },
        clear: function () {
            sessionStorage.clear();
        }
    };

    /**
     * 创建koGrid需要的viewModel
     *
     * @param p {url, param, columns, pageItem, operation, title}
     * @returns koGrid需要的viewModel
     */
    exports.createTableModel = function (p) {
        return {
            url: ko.observable(p.url),
            param: ko.observable(p.param),
            loadData: ko.observable(false),
            tableMainTheadTableColumns: ko.observable(p.columns),
            tablePageItem: ko.observable(p.pageItem),
            operationColumns: ko.observable(p.operation),
            tableTitle: ko.observable(p.title)
        };
    };

    /**
     * 将source里的值赋值给target里，将source中比target里多出来的值补充到target中
     *
     * @param target    目标对象
     * @param source    源对象
     * @returns {*}     处理过的目标对象
     */
    exports.extend = function(target, source) {
        $.each(source, function (key, val) {
            if(ko.isObservable(target[key])){
                target[key](val);
            }else{
                target[key] = val;
            }
        });
        return target;
    };

    /**
     * 将data数据中的所有属性转为可观测对象
     *
     * @param data 要处理的数据
     * @param items 数据中的object类型值的key
     */
    exports.mappingData = function (data, items) {
        var mapping = {};
        if (items && $.isArray(items) && items.length > 0) {
            $.each(items, function (index, item) {
                mapping[item] = {
                    update: function (options) {
                        return ko.observable(options.data);
                    }
                };
            });
        }
        return ko.mapping.fromJS(data, mapping);
    };

    exports.loadAjax = function (p) {
        return restClient(p).success(function (data) {
            p.model = p.model || {};
            if ($.isArray(data.data)) {
                // 处理list数据
                data.data = $.map(data.data, function (item) {
                    if (p.isObservable) {//可观测
                        return ko.mapping.fromJS($.extend($.extend({}, p.model), item));
                    } else {//不可观测
                        return $.extend($.extend({}, p.model), item);
                    }
                });
            } else if (data.data.content && $.isArray(data.data.content)) {
                // 处理page数据
                data.data.content = $.map(data.data.content, function (item) {
                    if (p.isObservable) {//可观测
                        return ko.mapping.fromJS($.extend($.extend({}, p.model), item));
                    } else {//不可观测
                        return $.extend($.extend({}, p.model), item);
                    }
                });
            } else {
                if (p.isObservable) {//可观测
                    data = ko.mapping.fromJS($.extend($.extend({}, p.model), data));
                } else {//不可观测
                    data = $.extend($.extend({}, p.model), data);
                }
            }
        });
    };

    /**
     * 验证字段，如果有错误，则显示所有的错误消息
     */
    exports.isErrors = function (viewModel) {
        if (ko.validation.group(viewModel)().length > 0) {
            ko.validation.group(viewModel).showAllMessages();
            return false;
        } else {
            return true;
        }
    };

    /**
     * 弹出有遮罩的页面
     *
     * @param obj   dialog返回的对象（必须有id字段）
     * @param viewModel
     */
    exports.showModalDialog = function (obj, viewModel, onShowAfter) {
        showDialogBefore(obj, viewModel, onShowAfter);
        obj.showModal();
    };

    /**
     * 弹出无遮罩弹出框
     *
     * @param obj  dialog返回的对象（必须有id字段）
     * @param viewModel
     */
    exports.showDialog = function (obj, viewModel, onShowAfter) {
        showDialogBefore(obj, viewModel, onShowAfter);
        obj.show();
    };


    /**
     * 弹出右下角提示框
     *
     * @param message 提示消息
     * @param type  类型：'success'和'error'
     * @param timeout 显示时间（默认2000ms）
     */
    exports.showAlertDialog = function (message, type, timeout) {
        var content = "";
        if (type == 'success') {
            content = '<span class="icon-ok" style=\'font-size: 16px;color: green;padding-right: 10px;\'></span>' + message
        } else if (type == 'error') {
            content = '<span class="icon-attention" style=\'font-size: 16px;color: red;padding-right: 10px;\'></span>' + message
        }
        var time = 2000;
        var alert = dialog({
            content: content,
            width: '240px',
            height: '30px',
            title: '消息',
            okValue: '确定',
            cancelValue: '取消',
            drag: false,
            onshow: function () {
                var obj = alert.node;
                $(obj)[0].style.left = "";
                $(obj)[0].style.top = "";
                $(obj)[0].style.right = "0";
                $(obj)[0].style.bottom = "0";
                //在两秒后将页面关掉
                if (timeout && timeout != null) {
                    time = timeout;
                }
                setTimeout(function () {
                    alert.close().remove();
                }, time);
            }
        });
        alert.show();
    };

    /**
     * 弹出确认对话框
     *
     * @param message 消息
     * @param okFun 点击确定按钮触发的方法
     * @param cancelFun 点击取消按钮触发的方法
     */
    exports.showConfirmDialog = function (message, okFun, cancelFun) {
        var confirm = dialog({
            content: '<span class="icon-attention" style=\'font-size: 16px;color: yellow;padding-right: 10px;\'></span>' + message,
            width: '270px',
            height: '10px',
            title: '消息',
            okValue: '确定',
            cancelValue: '取消',
            cancel: function () {
                cancelFun && cancelFun();
            },
            ok: function () {
                okFun && okFun();
            }
        });

        confirm.showModal();
    };

    /**
     * 获取拼音首字母
     * @param data 汉字
     */
    exports.translatePy = function (data) {
        var param = {
            url: 'translate/toPy',
            param: 'chinese=' + data
        };
        return exports.loadAjax(param);
    };

    /**
     * 获取当前登录用户
     * @returns {*}
     */
    exports.getCurrentUser = function() {
        return ko.currentUser.data;
    }

    //调用：accAdd(arg1,arg2)
    //返回值：arg1加上arg2的精确结果
    exports.accAdd = function(arg1, arg2) {
        var r1, r2, m;
        try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
        try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
        m = Math.pow(10, Math.max(r1, r2));
        return exports.toDecimal2((arg1 * m + arg2 * m) / m);
    };

    //调用：accSub(arg1,arg2)
    //返回值：arg1减去arg2的精确结果
    exports.accSub = function(arg1, arg2) {
        var r1, r2, m, n;
        try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
        try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
        m = Math.pow(10, Math.max(r1, r2));
        n = (r1 >= r2) ? r1 : r2;
        return exports.toDecimal2(((arg1 * m - arg2 * m) / m).toFixed(n));
    };

    //制保留2位小数，如：2，会在2后面补上00.即2.00
    exports.toDecimal2 = function(x) {
        var f = parseFloat(x);
        if (isNaN(f)) {
            return false;
        }
        f = Math.round(x*100)/100;
        var s = f.toString();
        var rs = s.indexOf('.');
        if (rs < 0) {
            rs = s.length;
            s += '.';
        }
        while (s.length <= rs + 2) {
            s += '0';
        }
        return s;
    };
    /**
     * 保存之前处理日期
     */
    exports.dealDateBeforeShow = function(dateModel, format){
        if(dateModel()){
            var date = new Date(dateModel());
            dateModel(exports.formatData(date, format));
        }
    };
    /**
     * 将日期类型的值转换为yyyy-mm-dd
     * @param date,日期格式的值
     * @param format
     * @returns {*}
     */
    exports.formatData = function(date, format) {
        var o =
        {
            "M+": date.getMonth() + 1, //month
            "d+": date.getDate(),    //day
            "h+": date.getHours(),   //hour
            "m+": date.getMinutes(), //minute
            "s+": date.getSeconds(), //second
            "q+": Math.floor((date.getMonth() + 3) / 3),  //quarter
            "S": date.getMilliseconds() //millisecond
        };
        if (/(y+)/.test(format))
            format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
        for (var k in o)
            if (new RegExp("(" + k + ")").test(format))
                format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
        return format;
    };

    /**
     * 计算机构级别
     * @param data
     */
    exports.calculationLevelNum = function (data) {
        return data * 1 + 1;
    };

    /**
     * 计算下级数据序号
     * @param data 上级序号100000
     * @param type 类型(org,menu)
     */
    exports.calculationSortNum = function (data, type) {
        var url = '';
        var param = '';
        if (type == 'org') {//(以6位为准，每两位为一个级别)
            url = 'rbacOrg/selectSortNum';
            param = 'parentOrgId=' + data;
        }
        if (type == 'menu') {//(以6位为准，每两位为一个级别)
            url = 'rbacMenu/selectSortNum';
            param = 'parentMenuId=' + data;
        }
        if (type == 'role') {//查询最大值
            url = 'rbacRole/selectSortNum';
        }
        if (type == 'operation') {
            url = 'rbacOperation/selectSortNum';
            param = 'menuId=' + data;
        }
        var paramObj = {
            url: url,
            param: param
        };
        return exports.loadAjax(paramObj);
    };

    /**
     * 获取当前页面操作权限
     */
    exports.getCurrentMenuOperations = function (htmlModel, arrayModel) {
        var currentPage = ko.dataFor($("body")[0]).currentMenu();
        var roleId = ko.currentUser.data.currentRoleId;
        var p = {
            url: '/rbacRoleMenu/findAll',
            param: 'search_EQ_role.id=' + roleId + '&search_EQ_menu.id=' + currentPage.id + "&sort_operation.sortNum=ASC"
        };
        exports.loadAjax(p).success(function (data) {
            if (data && data.data && data.data.length > 0) {
                var arrayOperations = [];
                var htmlOperations = [];
                $.each(data.data, function (index, item) {
                    if (item.operation) {
                        if (item.operation.type.id == '12') {
                            if (item.operation.operationContent) {
                                arrayOperations.push(eval('(' + item.operation.operationContent + ')'));
                            }
                        } else if (item.operation.type.id == '11') {
                            if (item.operation.operationContent) {
                                htmlOperations.push(item.operation.operationContent);
                            }
                        }
                    }
                });
                arrayModel(arrayOperations);
                htmlModel(htmlOperations);
            }
        });
    };

    /**
     * 判断字段不为空
     * @param value
     * @returns {boolean}
     */
    exports.isNotNull = function(value){
        if(value && value != null && value != "" && value.length != 0){
            return true;
        }else{
            return false;
        }
    };

    exports.logoutLoadAjax = function (p) {
        return logoutRestClient(p).success(function (data) {
            p.model = p.model || {};
            if ($.isArray(data.data)) {
                // 处理list数据
                data.data = $.map(data.data, function (item) {
                    if (p.isObservable) {//可观测
                        return ko.mapping.fromJS($.extend($.extend({}, p.model), item));
                    } else {//不可观测
                        return $.extend($.extend({}, p.model), item);
                    }
                });
            } else if (data.data.content && $.isArray(data.data.content)) {
                // 处理page数据
                data.data.content = $.map(data.data.content, function (item) {
                    if (p.isObservable) {//可观测
                        return ko.mapping.fromJS($.extend($.extend({}, p.model), item));
                    } else {//不可观测
                        return $.extend($.extend({}, p.model), item);
                    }
                });
            } else {
                if (p.isObservable) {//可观测
                    data = ko.mapping.fromJS($.extend($.extend({}, p.model), data));
                } else {//不可观测
                    data = $.extend($.extend({}, p.model), data);
                }
            }
        });
    };

//---------------- 内部函数 ------------------------------

    function restClient(p) {
        var isBusy = false;
        var tempUrl = "";

        function myRestClient(p) {
            if (isBusy && tempUrl == p.url) return;
            var url = p.url;
            if (p.param) {
                url = url + "?" + p.param;
            }
            var data = null;
            if (p.jsonParam) {
                data = p.jsonParam;
            }

            tempUrl = url;
            isBusy = true;
            return $.ajax({
                type: 'POST',
                contentType: 'application/json;charset=UTF-8',
                url: url,
                data: data || '{}',
                beforeSend: function (xhr) {
                    if (exports.sessionStorageUtil.getItem("X-AUTH-TOKEN")) {
                        xhr.setRequestHeader('X-AUTH-TOKEN', exports.sessionStorageUtil.getItem("X-AUTH-TOKEN").token);
                    }
                    p.beforeFun && p.beforeFun(xhr);
                },
                complete: function () {
                    isBusy = false;
                    tempUrl = "";
                },
                success: function (data, textStatus, request) {
                    isBusy = false;
                    tempUrl = "";
                    if (request.getResponseHeader("X-AUTH-TOKEN")) {
                        exports.sessionStorageUtil.setItem("X-AUTH-TOKEN", {token: request.getResponseHeader("X-AUTH-TOKEN")});
                    }
                    p.successFun && p.successFun(data);
                },
                error: function (xhr, txtStatus, error) {
                    isBusy = false;
                    tempUrl = "";
                    if (4 == xhr.readyState && 403 == xhr.status) {
                        var vm = ko.dataFor($("body")[0]);
                        vm.initPage("app/login/login");
                    }
                    if (1001 == xhr.status) {
                        exports.showAlertDialog('用户名输入错误!', 'error');
                        return;
                    }
                    if (1002 == xhr.status) {
                        exports.showAlertDialog('密码输入错误!', 'error');
                        return;
                    }
                    p.errorFun && p.errorFun();
                }
            });
        }

        return myRestClient(p);
    }

    function showDialogBefore(obj, viewModel, onShowAfter) {
        if (obj.url) {
            $.get(obj.url, null, function (response, status, xhr) {
                obj.content(response);
                var dlg = $("#content\\:" + obj.id);
                if (viewModel) {
                    ko.applyBindings(viewModel, dlg[0]);
                }
                if (obj.options.height) {
                    dlg.perfectScrollbar();
                }
                onShowAfter && onShowAfter();
            });
        }
    }

    String.prototype.endWith = function (s) {
        if (s == null || s == "" || this.length == 0 || s.length > this.length) {
            return false;
        }
        if (this.substring(this.length - s.length) == s) {
            return true;
        } else {
            return false;
        }
        return true;
    };

    String.prototype.startWith = function (s) {
        if (s == null || s == "" || this.length == 0 || s.length > this.length) {
            return false;
        }
        if (this.substr(0, s.length) == s) {
            return true;
        } else {
            return false;
        }
        return true;
    };


    function logoutRestClient(p) {
        var isBusy = false;
        var tempUrl = "";

        function logoutRestClient(p) {
            return $.ajax({
                type: 'POST',
                contentType: 'application/json;charset=UTF-8',
                url: p.url,
                data: p.data,
                beforeSend: function (xhr) {
                    exports.sessionStorageUtil.clear();
                    p.beforeFun && p.beforeFun(xhr);
                },
                complete: function () {
                    isBusy = false;
                    tempUrl = "";
                },
                success: function (data, textStatus, request) {
                    isBusy = false;
                    tempUrl = "";
                    p.successFun && p.successFun(data);
                },
                error: function (xhr, txtStatus, error) {
                    isBusy = false;
                    tempUrl = "";
                    if (4 == xhr.readyState && 403 == xhr.status) {
                        var vm = ko.dataFor($("body")[0]);
                        vm.initPage("app/login/login");
                    }
                    p.errorFun && p.errorFun();
                }
            });
        }

        return logoutRestClient(p);
    }
}));